/**
 * Created by sun on 2015/3/12.
 */
package com.jbm.jbmsupplier.util;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.Method;

public class OHDecoder extends CumulativeProtocolDecoder
{
//    private static final Logger LOGGER = Logger.getLogger(OHDecoder.class);

    private final String charset;

    public OHDecoder(String charset) {
        this.charset = charset;
    }

    protected boolean doDecode(IoSession session, IoBuffer in,
                               ProtocolDecoderOutput out) throws Exception
    {
        int protoc_type = Integer.parseInt ( ( String )session.getAttribute( "PROTOC_TYPE") );
        if (in.remaining() >= 4)
        {
            in.mark();// 标记当前位置，以便reset

            int len = 0;
            byte[] blen = new byte[4];
            in.get(blen);
            byte type = blen[0];
            type &= 0xf0;
            if ( protoc_type == -1 )
                session.setAttribute("PROTOC_TYPE", String.valueOf(type));
            len = (int) ((blen[3] & 0xFF)
                    | ((blen[2] & 0xFF)<<8)
                    | ((blen[1] & 0xFF)<<16)
                    | ((blen[0] & 0x0F)<<24));
//          int length = StringUtils.bytesToInt(lenBytes);

            if (len > in.remaining()) {// 如果消息内容不够，则重置，相当于不读取size
                in.reset();
                return false;// 接收新数据，以拼凑成完整数据
            } else {
                Object to = null;

                if ( type == 0 )
                {
                    byte[] bbIn = new byte[len];

                    in.get(bbIn, 0, len);

                    ByteArrayInputStream bais = new ByteArrayInputStream(bbIn);
                    ObjectInputStream ois = new ObjectInputStream(bais);
                    to = ois.readObject();
                }else if ( type == 0x10 )
                {
                    byte[] bslen = new byte[2];
                    in.get(bslen);
                    int strlen = ((bslen[1] & 0xFF)
                            | ((bslen[0] & 0xFF)<<8));
                    byte[] bname = new byte[strlen];
                    in.get(bname,0,strlen);
                    String cname = new String ( bname, "UTF8");
                    String pbname = "com.jbm.jbmsupplier.pb.PB"+cname+"$"+cname;
                    Object pbb = null;

                    byte[] bbIn = new byte[len-strlen-2];
                    in.get(bbIn,0,len-strlen-2);

                    if ( cname.equals("String"))
                    {
                        to = new String ( bbIn, "UTF8");
                    }else
                    {
                        try
                        {
                            Method nb = Class.forName(pbname).getMethod("parseFrom", byte[].class);
                            pbb = nb.invoke(null, bbIn);
                            to = TransClass.ProtocolBufferToI(pbb);
                        } catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                }

                out.write(to);

                if (in.remaining() > 0) {// 如果读取内容后还粘了包，就让父类再给一次，进行下一次解析
                    // System.out.println("package left="+in.remaining()+" data="+in.toString());
                }
                return true;// 这里有两种情况1：没数据了，那么就结束当前调用，有数据就再次调用
            }
        }
        return false;// 处理成功，让父类进行接收下个包
    }
}
